package cn.iocoder.yudao.framework.mybatis.autotable.scanner;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.ClassUtils;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.HashSet;
import java.util.Set;

public class TableScanner {
    private static final ResourcePatternResolver RESOURCE_PATTERN_RESOLVER =
            new PathMatchingResourcePatternResolver();

    private static final MetadataReaderFactory METADATA_READER_FACTORY =
            new CachingMetadataReaderFactory(RESOURCE_PATTERN_RESOLVER);

    public static Set<Class<?>> scanEntities(String... basePackages) {
        Set<Class<?>> entities = new HashSet<>();
        for (String basePackage : basePackages) {
            try {
                // 处理通配符路径
                String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                        resolveBasePackage(basePackage) + "/**/*.class";

                Resource[] resources = RESOURCE_PATTERN_RESOLVER.getResources(packageSearchPath);

                for (Resource resource : resources) {
                    if (resource.isReadable()) {
                        MetadataReader metadataReader = METADATA_READER_FACTORY.getMetadataReader(resource);
                        if (isEntityCandidate(metadataReader)) {
                            String className = metadataReader.getClassMetadata().getClassName();
                            entities.add(Class.forName(className));
                        }
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException("Failed to scan entities in package: " + basePackage, e);
            }
        }
        return entities;
    }

    /**
     * 将包路径转换为资源路径
     * 支持格式: com.**.entity → com/**entity
     */
    private static String resolveBasePackage(String basePackage) {
        return ClassUtils.convertClassNameToResourcePath(basePackage);
    }

    /**
     * 检查类是否带有@TableName注解
     */
    private static boolean isEntityCandidate(MetadataReader metadataReader) throws Exception {
        return new AnnotationTypeFilter(TableName.class)
                .match(metadataReader, METADATA_READER_FACTORY);
    }
}